//
//  LRPhotoBrowserCell.swift
//  LRWeibo
//
//  Created by 雷路荣 on 15/12/30.
//  Copyright © 2015年 leilurong. All rights reserved.
//

import UIKit

import SDWebImage

import SVProgressHUD

import FLAnimatedImage

let LRImageViewMinimumZoomScale: CGFloat = 0.5

// 当缩放完毕小于此缩放比例时,自动关闭控制器
let dismissZoomScale: CGFloat = 0.75

/**
 *  cell缩放的代理
 */
protocol LRPhotoBrowserCellDelegate: NSObjectProtocol {
    /// 获取代理(控制器)的背景
    func viewForTransparent() -> UIView
    /// 通知控制器关闭
    func cellForDismissController()
    /// 关闭时返回缩略图的位置
    func targetRectForDismissController() -> CGRect
}

class LRPhotoBrowserCell: UICollectionViewCell, UIScrollViewDelegate {
    
    /// cell缩放ImageView的代理
    weak var delegate: LRPhotoBrowserCellDelegate?
    
    var imageURL:NSURL? {
        didSet{
            // cell会使用上一张的缓存图片,在显示图片之前清空上一张的缓存
            imageView.image = nil
            
            ///清空scrollView和imageView的属性,赋值cell复用
            resetProperties()
            
            /*--消耗内存大
            /// 控制器设置了url,使用SDWebImage去加载图片
            /// 1.去内存缓存加载
            /// 2.内存缓存没有,去磁盘加载
            /// 3.磁盘上面也没有,就会去网络上面加载图片
            /// 4.从网络加载图片后,会缓存到内存和磁盘
            // 下载之前显示菊花
            indicatorView.startAnimating()
            //下载显示图片----------消耗内存大
            imageView.sd_setImageWithURL(imageURL) { (image, error, _, _) -> Void in
                //关闭菊花
                self.indicatorView.stopAnimating()
                if error != nil {
                    return
                }
                // 获取到图片,修改imageView的大小
                self.layoutImageView(image)
            }
            */
            
            // 判断图片是否已经下载过
            // SDWebIamage默认缓存图片的路径
            let cachePath = SDWebImageManager.sharedManager().imageCache.defaultCachePathForKey(imageURL?.absoluteString)
            //加载数据
            let data = NSData(contentsOfFile: cachePath)
            if data != nil {
                // 表示之前有缓存
                let image = UIImage(data: data!)
                self.setImage(image!, data: data!)
                return
            }
            // 没有缓存，下载图片并显示
            // 使用SDWebImage来下载图片
            SDWebImageDownloader.sharedDownloader().downloadImageWithURL(imageURL, options: SDWebImageDownloaderOptions(rawValue: 0), progress: { (receive, total) -> Void in
                //计算进度
                let progress = Float(receive) / Float(total)
                    //print("线程: \(NSThread.currentThread())---进度：\(progress)")//子线程
                    // 显示图片,需要在主线程上面执行
                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
                        //进度提示
                        SVProgressHUD.showProgress(progress)
                    })
                
                }) { (image, data, error, finished) -> Void in
                     //print("下载图片完成: \(NSThread.currentThread())")//子线程
//                     我们手动调用的下载,SDWebImage不会自动缓存起来,需要我们手动来缓存,下次直接使用缓存好的图片,不需要在去网路上加载
//                     image: 要保存的图片
//                     recalculateFromImage: 保存的图片是否要重新压缩,
//                     imageData: 保存图片的二进制
//                     forKey: SDWebImage保存图片,使用url地址作为key进行MD5加密
//                     toDisk: 是否要保存到沙盒
                    SDWebImageManager.sharedManager().imageCache.storeImage(image, recalculateFromImage: false, imageData: data, forKey: self.imageURL?.absoluteString, toDisk: true)
                    // 显示图片,需要在主线程上面执行
                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
                        self.setImage(image, data: data)
                    })
                
            }
        }
    }
    
    ///设置显示的图片
    private func setImage(image: UIImage, data: NSData) {
        // 判断图片类型,是否是gif图片
        let gif = self.imageURL!.absoluteString.lowercaseString.hasSuffix("gif")
        // 如果不是gif图片
        if !gif {
            //显示普通图片
            self.imageView.image = image
        }else{
            //创建gifImage
            let animatedImage = FLAnimatedImage(animatedGIFData: data)
            //显示gif图片
            self.imageView.animatedImage = animatedImage
        }
        SVProgressHUD.dismiss()
        //修改图片大小
        self.layoutImageView(image)
    }
    
    ///清空scrollView和imageView的属性
    private func resetProperties() {
        imageView.transform = CGAffineTransformIdentity
        scrollView.contentInset = UIEdgeInsetsZero
        scrollView.contentSize = CGSizeZero
        scrollView.contentOffset = CGPointZero
    }
    
    /*
    将图片等比例缩放到宽度等于屏幕的宽度
    1.长图,高度大于屏幕的高度
    长图从顶部开始显示
    2.短图,高度小于屏幕的高度
    短图居中显示
    */
    /// 重新布局imageView的frame
    private func layoutImageView(image: UIImage) {
        //新宽度为屏幕宽度
        let newWidth = UIScreen.mainScreen().bounds.width
        // 新的高度 / 新的宽度 = 原来的高度 / 原来的宽度
        let newHeight = newWidth * image.size.height / image.size.width
        // 判断长短图
        if newHeight < UIScreen.mainScreen().bounds.height {
            // 短图,居中显示,图片放大图片frame不会变，想看图片其余部分很难
            imageView.frame = CGRectMake(0, 0, newWidth, newHeight)
            // 设置上下偏移值
            scrollView.contentInset = UIEdgeInsetsMake((UIScreen.mainScreen().bounds.height - newHeight) * 0.5, 0, 0, (UIScreen.mainScreen().bounds.height - newHeight) * 0.5)
        }else {
            //长图
            imageView.frame = CGRectMake(0, 0, newWidth, newHeight)
            // 设置scrollView contentSize,使图片可以滚动显示
            scrollView.contentSize = CGSizeMake(newWidth, newHeight)
        }
    }
    
    //MARK: - 构造方法
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        prepareUI()
    }
    ///准备控件
    func prepareUI() {
        
        scrollView.delegate = self
        scrollView.maximumZoomScale = 2
        scrollView.minimumZoomScale = LRImageViewMinimumZoomScale
        //添加子控件
        contentView.addSubview(scrollView)
        //注意imageView是添加给scrollView,不然不能滚动
        scrollView.addSubview(imageView)
        contentView.addSubview(indicatorView)
        
        // 添加约束
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        indicatorView.translatesAutoresizingMaskIntoConstraints = false
        // scrollView填充父控件
        contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[sv]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["sv" : scrollView]))
        contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[sv]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["sv" : scrollView]))
        // imageView宽高不固定,不直接使用autoLayout约束,通过frame来确定位置
        
        // 菊花, 父控件居中
        contentView.addConstraint(NSLayoutConstraint(item: indicatorView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0))
        contentView.addConstraint(NSLayoutConstraint(item: indicatorView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))

    }
    
    //MARK: - 懒加载
    /// 图片放大后用于滚动查看大图
    private var scrollView: UIScrollView = UIScrollView()
    /// 显示图片
    var imageView: LRImageView = LRImageView()
    /// 菊花,显示加载进度
    private lazy var indicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
    
    //MARK: - UIScrollViewDelegate 代理方法
    ///缩放那个view
    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        return imageView
    }
    
    /// scrollView每次缩放图片都会调用
    func scrollViewDidZoom(scrollView: UIScrollView) {
        // 修改控制器的背景透明度
        // 获取到要修改透明度的view
        let backgView = delegate?.viewForTransparent()
        // 计算alpha 0.5 - 2
        var alpha = imageView.transform.a * 0.7 + 0.2
        
        if alpha < 1 {
            backgView?.alpha = alpha
        }else{
            alpha = 1
        }
    }
    
    /// scrollView缩放结束会调用
    /// 当我们的缩放小于最小缩放比例时,不会立马scrollViewDidEndZooming,而会先自动动画到左上角,再调用scrollViewDidEndZooming,来通知我们缩放完成,我们不让他缩放到比指定的最小缩放比例还小，覆盖imageView的transfrom,不让scrollView将imageView的transfrom设置的比最小缩放比例还小
    /// 注意:当scrollView缩放后,imageView的bounds不会变化的.frame会变化,要获取缩放后的大小,使用frame
    func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView?, atScale scale: CGFloat) {
        
        // 判断如果缩放比例小于指定的比例直接关闭控制器
        if scale < dismissZoomScale {
            // 不能直接关闭控制器,frame不准
            //delegate?.cellForDismissController()
            
            if let newFrame = delegate?.targetRectForDismissController() {
                
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    
                    self.imageView.contentMode = UIViewContentMode.ScaleAspectFill
                    self.imageView.clipsToBounds = true
                    self.imageView.frame = CGRect(origin: CGPointZero, size: newFrame.size)
                    // 顶部和左边需要间距,不然会朝左上方向弹一下才回到原来位置
                    scrollView.contentInset = UIEdgeInsets(top: newFrame.origin.y, left: newFrame.origin.x, bottom: 0, right: 0)
                    
                    // 当图片是长图的时候会发现origin.y值是不对的,悬空在原来位置上方，突然归位
                    scrollView.contentOffset.x = -newFrame.origin.x
                    scrollView.contentOffset.y = -newFrame.origin.y
                    
                    }, completion: { (_) -> Void in
                        //关闭控制器
                        self.delegate?.cellForDismissController()
                })
            }
            
        }else{
            //居中图片
            var offX = (scrollView.bounds.width-imageView.frame.width) * 0.5
            var offY = (scrollView.bounds.height-imageView.frame.height) * 0.5
            // 判断 offestX,offestY 不能小于0, offestX > 0 会往右边顶, offestX < 0会往左边扯,有一些内容会看不到,当offestX < 0 时 offestX = 0
            offX = offX < 0 ? 0 : offX
            offY = offY < 0 ? 0 : offY
            UIView.animateWithDuration(0.25) { () -> Void in
                scrollView.contentInset = UIEdgeInsets(top: offY, left: offX, bottom: 0, right: 0)//UIEdgeInsetsMake(offY, offX, 0, 0)
        }
      }
    }
    
    
}
